package com.xplay.xpocker.service.gaming.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.xplay.xpocker.config.security.CurrentUser;
import com.xplay.xpocker.dvo.AbstractRoom;
import com.xplay.xpocker.dvo.GameRuMahjongUserState;
import com.xplay.xpocker.dvo.MahjongInfoStruct;
import com.xplay.xpocker.entity.*;
import com.xplay.xpocker.mapper.GameRuMahjongMapper;
import com.xplay.xpocker.mapper.GameRuMahjongUserMapper;
import com.xplay.xpocker.room.mahjong.dto.MahjongRoomInfo;
import com.xplay.xpocker.room.mahjong.dto.MahjongRoomRule;
import com.xplay.xpocker.service.GameRuMahjongFractionService;
import com.xplay.xpocker.service.GameRuMahjongLogsService;
import com.xplay.xpocker.service.gaming.GameRuMahjongService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xplay.xpocker.service.gaming.GameRuMahjongUserService;
import com.xplay.xpocker.service.gaming.GameRuRoomService;
import com.xplay.xpocker.service.gaming.GameRuMahjongOpenDealService;
import com.xplay.xpocker.util.Assertion;

import com.xplay.xpocker.util.JacksonStringUtil;
import com.xplay.xpocker.util.ObjectUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author xplay
 * @since 2023-08-19
 */
@Slf4j
@Service
public class GameRuMahjongServiceImpl extends ServiceImpl<GameRuMahjongMapper, GameRuMahjong> implements GameRuMahjongService {


    @Autowired
    private GameRuRoomService gameRuRoomService;
    @Autowired
    private GameRuMahjongOpenDealService gameRuUserOpenDealService;

    @Autowired
    private GameRuMahjongUserMapper mahjongUserMapper;

    @Autowired
    private GameRuMahjongUserService ruMahjongUserService;

    @Autowired
    private GameRuMahjongLogsService mahjongLogsService;

    @Autowired
    private GameRuMahjongFractionService fractionService;

    @Override
    public GameRuMahjong queryByRoomId(BigDecimal roomId) {
        LambdaQueryWrapper<GameRuMahjong> wrapper = Wrappers.lambdaQuery(GameRuMahjong.class).eq(GameRuMahjong::getRoomId, roomId);
        return getOne(wrapper);
    }

    @Override
    public AbstractRoom<MahjongRoomRule, MahjongRoomInfo, GameRuMahjongLogs> queryRoomInfo(String roomCode) {
        BigDecimal userId = null;
        try {
            userId = CurrentUser.getUserId();
        } catch (Exception e) {
            log.debug("用户信息加载失败...");
        }
        GameRuRoom gameRuRoom = gameRuRoomService.queryRoomByCode(roomCode);
        log.info("运行时房间信息:{}",JacksonStringUtil.objectToString(gameRuRoom));
        Assertion.isNull(gameRuRoom, "运行时房间信息不存在,请检查");
        AbstractRoom<MahjongRoomRule, MahjongRoomInfo, GameRuMahjongLogs> roomInfo = MahjongInfoStruct.INSTANCE.roomToMahjongRoom(gameRuRoom);
        log.info("返回房间信息:{}",JacksonStringUtil.objectToString(roomInfo));
        MahjongRoomRule roomRule = JacksonStringUtil.objectCase(gameRuRoom.getMetadata(), MahjongRoomRule.class);
        roomInfo.setRule(roomRule);
        // 获取运行中麻将信息
        GameRuMahjong mahjongRoom = this.queryByRoomId(gameRuRoom.getId());
        MahjongRoomInfo mahjongRoomInfo = MahjongInfoStruct.INSTANCE.toDTO(mahjongRoom);
        if (roomRule != null) {
            roomRule.setRoomType(gameRuRoom.getType());
        }
        mahjongRoomInfo.setStatus(roomInfo.getStatus());
        List<GameRuMahjongUserState> allUsers = mahjongUserMapper.queryByRoomId(gameRuRoom.getId());
        mahjongRoomInfo.setAllUser(allUsers);
        if (ObjectUtils.notEmpty(allUsers) && userId != null) {
            List<GameRuMahjongUserState> otherUsers = new ArrayList<>();
            for (GameRuMahjongUserState item : allUsers) {
                if (item.getUserId().equals(userId)) {
                    mahjongRoomInfo.setCurrentUser(item);
                } else {
                    otherUsers.add(item);
                }
                if (ObjectUtils.notEmpty(item.getSwapCardOut())) {
                    item.setSwapOutStatus(true);
                }
                if (ObjectUtils.notEmpty(item.getSwapCardIn())) {
                    item.setSwapInStatus(true);
                }
            }
            mahjongRoomInfo.setOtherUsers(otherUsers);
        }
        roomInfo.setGameInfo(mahjongRoomInfo);
        return roomInfo;
    }

    /**
     * 持久化房间状态
     *
     * @param roomInfo
     */

    @Override
    @Transactional
    public void updateRoomInfo(AbstractRoom<MahjongRoomRule, MahjongRoomInfo, GameRuMahjongLogs> roomInfo) {
        MahjongRoomInfo gameInfo = roomInfo.getGameInfo();
        Date updateDate = new Date();
        gameInfo.setUpdateDate(updateDate);
        roomInfo.setUpdateDate(gameInfo.getUpdateDate());
        gameInfo.setStatus(roomInfo.getStatus());
        gameRuRoomService.updateById(roomInfo);
        boolean update = updateById(gameInfo);
        Assertion.isTrue(!update, "请稍后重试。");
        ruMahjongUserService.updateById(gameInfo.getCurrentUser());
        // 这里要不要考虑一下单独处理 碰杠的 事件 内部  事务了
        for (GameRuMahjongUserState user : gameInfo.getAllUser()) {
            ruMahjongUserService.updateById(user);
            if (ObjectUtils.isEmpty(user.getOpenDeal())) {
                gameRuUserOpenDealService.cleanByUserId(user.getUserId());
            }
            if (ObjectUtils.notEmpty(user.getOpenDeal())) {
                gameRuUserOpenDealService.saveOrUpdateBatch(user.getOpenDeal());
            }
            if (ObjectUtils.isEmpty(user.getFractions())) {
                fractionService.cleanByUserId(user.getUserId());
            }
            if (ObjectUtils.notEmpty(user.getFractions())) {
                fractionService.saveOrUpdateBatch(user.getFractions());
            }
        }
        if (ObjectUtils.notEmpty(roomInfo.getLogs())) {
            mahjongLogsService.saveOrUpdateBatch(roomInfo.getLogs());
        }
    }
}
